"""
图像校正：透视变换
综合案例1
"""
import cv2
import math
import numpy as np

img = cv2.imread('../data/paper.jpg')
cv2.imshow('img',img)

# 图像灰度化
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# 图像二值化
# t,binary = cv2.threshold(img_gray,190,255,cv2.THRESH_BINARY)
# cv2.imshow('binary',binary)

# 图像模糊 高斯
img_gaussian_blur = cv2.GaussianBlur(img_gray,(5,5),0)
# cv2.imshow('img_gaussian_blur',img_gaussian_blur)

# 膨胀
dilate = cv2.dilate(img_gaussian_blur,(3,3))

# 边沿检测
# sobel
# sobel = cv2.Sobel(img_gray,cv2.CV_64F,1,1)
# cv2.imshow('sobel',sobel)

# laplacian
# lap = cv2.Laplacian(img_gray,cv2.CV_64F)
# cv2.imshow('lap',lap)

# Canny
canny = cv2.Canny(dilate,50,180)
# cv2.imshow('canny',canny)

# 查找轮廓,返回轮廓坐标点，和关系坐标点
cnts,hie = cv2.findContours(canny,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
# print(len(cnts))

cv2.drawContours(img,cnts,-1,(0,0,255))
# cv2.imshow('img_cnt',img)

# 查看轮廓大小
# 1.使用shape查看大小
# for cnt in cnts:
#     print(cnt.shape)

# 2.按面积进行排序判断大小，根据面积对轮廓进行排序
docCnt = None # 保存轮廓的四个顶点
if len(cnts) > 0:
    cnts = sorted(cnts,
                  key=cv2.contourArea, # 面积
                  reverse=True) # 降序

    for c in cnts: # 遍历排序之后的轮廓
        eps = 0.02 * cv2.arcLength(c,True)
        approx = cv2.approxPolyDP(c,eps,True)

        if len(approx) == 4:
            docCnt = approx
            break

print(docCnt)

points = []
# 绘制四个角的顶点
for peak in docCnt:
    peak = peak[0]
    cv2.circle(img,tuple(peak),10,(0,0,255))

    points.append(peak)

# cv2.imshow('point',img)

# 左上角 左下角，右下角，右上角
h = int(math.sqrt((points[0][0] - points[1][0])**2 + (points[0][1] - points[1][1])**2))
# print(h)
w = int(math.sqrt((points[0][0] - points[3][0])**2 + (points[0][1] - points[3][1])**2))

# 构建透视变换矩阵需要的两组坐标
src = np.float32([points[0],
                  points[1],
                  points[2],
                  points[3]])

dst = np.float32([[0,0],
                  [0,h],
                  [w,h],
                  [w,0]])

# 生成透视变换的矩阵
M = cv2.getPerspectiveTransform(src,dst)
# 进行透视变换
result = cv2.warpPerspective(img_gray, M,(w,h))

cv2.imshow('result',result)

cv2.waitKey()
cv2.destroyAllWindows()